use crate::{
    app_writer::AppResult,
    middleware::{
        admin::admin_check,
        cors::cors_middleware,
        jwt::{handle_jwt, jwt_middleware, JwtClaims},
    },
};
use file::{delete_file, get_download_file, get_files, post_upload_file, post_upload_file_quick};
use paper::{delete_paper, get_papers, get_share_paper, post_add_paper, put_update_paper};
use salvo::{
    prelude::{CatchPanic, JwtAuthDepotExt, Logger, OpenApi, Scalar},
    Depot, Router,
};
use search::{get_search_file, get_search_paper};

use self::{
    demo::hello,
    user::{delete_user, get_users, get_whoami, post_add_user, post_login, put_update_user},
};
pub mod demo;
pub mod file;
pub mod paper;
pub mod search;
mod static_routers;
pub mod user;

pub fn router() -> Router {
    let mut no_auth_routers = vec![Router::with_path("/api/login")
        .get(post_login)
        .post(post_login)];

    let _cors_handler = cors_middleware();

    let mut need_auth_routers: Vec<Router> = vec![
        Router::with_path("/api/users").get(get_users).push(
            Router::new()
                .post(post_add_user)
                .push(
                    Router::with_path("<id>")
                        .put(put_update_user)
                        .delete(delete_user),
                )
                .hoop(admin_check),
        ),
        Router::with_path("/api/whoami").get(get_whoami),
        Router::with_path("/api/papers")
            .get(get_papers)
            .post(post_add_paper)
            .push(
                Router::with_path("<id>")
                    .put(put_update_paper)
                    .delete(delete_paper)
                    .push(
                        Router::with_path("/files")
                            .get(get_files)
                            .post(post_upload_file)
                            .push(
                                Router::with_path("<hash>")
                                    .get(get_download_file)
                                    .post(post_upload_file_quick)
                                    .delete(delete_file),
                            ),
                    ),
            ),
        Router::with_path("/api/share").get(get_share_paper),
        Router::with_path("/api/search")
            .push(Router::with_path("/papers").get(get_search_paper).post(get_search_paper))
            .push(Router::with_path("/files").get(get_search_file).post(get_search_file)),
    ];
    let router = Router::new()
        .hoop(_cors_handler)
        .hoop(Logger::new())
        .hoop(CatchPanic::new())
        .get(hello)
        .append(&mut no_auth_routers)
        .push(
            Router::new()
                .append(&mut need_auth_routers)
                .hoop(jwt_middleware())
                .hoop(handle_jwt),
        );
    let doc = OpenApi::new("salvo web api", "0.0.1").merge_router(&router);
    router
        .push(doc.into_router("/api-doc/openapi.json"))
        .push(Scalar::new("/api-doc/openapi.json").into_router("scalar"))
}

pub fn get_userid_from_jwt<'a>(depot: &'a mut Depot) -> AppResult<&'a str> {
    let user_id = &depot
        .jwt_auth_data::<JwtClaims>()
        .ok_or(anyhow::anyhow!("jwt提取失败"))?
        .claims
        .user_id
        .as_str();
    Ok(user_id)
}
